package core.actor.core
{
	import core.actor.ActorCacheManager;
	
	import core.Resource.AniPack;
	import core.Resource.DressPack;
	import core.Resource.DressPackManager;
	
	import findPath.PointClassification;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Graphics;
	import flash.display.SpreadMethod;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import loader.TempLoader;

	public class Bones extends EventDispatcher
	{
		
		public static const ACTION_FINISH:String = "TGP_BONES_ACTION_FINISH";
		
		private var _curFrame:int = 1;
		
		//记录当前骨骼和角色类型
		private var _chrType:String = "";//角色类型，各部分装扮号拼接
		private var _actionName:String = "";
		
		
		private var _aniData:Array;
		private var _dressData:Array;
		private var _aniLength:int;
		
		private var _flip:Boolean = false;
		
		
		private var _template:Array;
		
		private var _initDraw:Boolean = false;
		private var _jumpFrame:Boolean = false;
		private var _alternateFrame:int = 1;
		
		private var _layers:Vector.<Bitmap>;
	
		private var _layersRect:Array;
		
		private var _currentPhase:int = 0; 
		
		//private var _oriTemplateSize:Array;
		private var _oriTemplate:Array;
		
		private var _ani:AniPack;
		
		
		//TODO:第一次画完cache到bmd序列
		//传入bitmap序列必须先完成初始化
		public function Bones(layers:Vector.<Bitmap>)
		{
			_layers = layers;
			_layersRect = [];
			_template = [];
			_oriTemplate = [];
			//_oriTemplateSize = [];
			//初始化template
			for(var i:int  = 0;i<layers.length;i++)
			{
				_template[layers[i].name] = layers[i].bitmapData;
				_oriTemplate[layers[i].name] = layers[i].bitmapData;
				//_oriTemplateSize[layers[i].name] = layers[i].bitmapData.rect;
			}
		}
		
		public function setAnimation(aniPack:AniPack):void//TODO：添加名字
		{
			//设置骨骼动画
			clear();
			_ani = aniPack;

		}
		
		//dressCode:face|headdress|Armet|Hair|Wing|Cloth|Weapon|Belt|Trousers|Shoes|Shadow|HeadUpRing|HeadBehindRing|FootRing|BodyRing
		//没有部分留空
		public function setDress(res:Vector.<DressPack>,dressCodeSting:String):void
		{
			_chrType = dressCodeSting;//根据dress信息给chrType复制
			_dressData = [];
			for(var i:int;i<res.length;i++)
			{
				_dressData[res[i].name.substr(2,2)] = res[i];
			}
			
		}
		
		//TODO：udpate时，判断部位，（翅膀，武器特殊处理），重绘，且要重新编码dressCode
		public function updateDress(data:DressPack,name:String):void
		{
			////清空原有缓存，重新缓存
		}
		
		/**
		 * 0：都缓存
		 * 1：不缓存
		 * 2：隔帧缓存
		 * */
		public function set cachePolicy(type:String):void
		{
			if(type == "All")
				cacheFrameAlernate(0);
			else if(type == "None")
				cacheFrameAlernate(1);
			else if(type == "Alternate")
				cacheFrameAlernate(2);
			
		}
		
		public function set flip(b:Boolean):void
		{	
			_flip=b;
		}
		
		public function update():void
		{
			if(_ani.state == 1 && _ani.data!=null)
			{
				_actionName = _ani.name;
				_aniData = _ani.data.ani;
				_aniLength = _aniData.length;
			}
			else 
			{
				return;
			}
			//TODO:帧数+1，播下一帧动ui画
			if(!_jumpFrame || ((_curFrame&1)!=0))
			{
				updateBonesAction();
			}
			
			_curFrame+=1;
			if(_curFrame>_aniLength)
			{
				_curFrame = 1;
				//_initDraw = false;
				if(_currentPhase == 0)
					_currentPhase = 1;
				else if(_currentPhase == 1)
					_currentPhase = 2;
				this.dispatchEvent(new Event(ACTION_FINISH));
			}
		}
		
		public function set jumpFrame(b:Boolean):void
		{
			_jumpFrame = b;
		}
		
		public function goto(frameCount:int,play:Boolean = true):void
		{
			//跳往特定帧,需要考虑initDraw
		}
		
		public function gotoFrame1():void
		{
			//重置动画位置
			_curFrame = 1;
		}
		
		//0是都缓存，1是都不缓存
		private function cacheFrameAlernate(alternateFrame:int):void
		{
			_alternateFrame = alternateFrame;
		}
		
		private function clear():void
		{
			_curFrame = 1;
			//_flip = 0;
			_aniLength = 0;
			_layersRect = [];
			for(var i:int = 0;i<_layers.length;i++)
			{
				_template[_layers[i].name] = _oriTemplate[_layers[i].name];
			}
			_currentPhase = 0;
		}
		
		
		public function dispose():void
		{
			clear();
			_aniData = null;
			_dressData = null;
		}
		
		
		private function getTransformedOffset(ori:Point,scaleX:Number,scaleY:Number,rotation:Number,offsetX:Number,offsetY:Number):Point
		{
			var result:Point = new Point();
			
			//缩放
			ori.x*=-scaleX;
			ori.y*=scaleY;
			//旋转
			var x:Number = ori.x*Math.cos(rotation)+ori.y*Math.sin(rotation);
			var y:Number = ori.x*Math.sin(rotation)-ori.y*Math.cos(rotation);
			result.x = -x;
			result.y = -y;
			//位移
			result.offset(offsetX,offsetY);
			return result;
		}
		
		private function drawByData(boneName:String,data:BoneData,bmd:BitmapData):BitmapData
		{
			//获取骨骼所属dress包
			var packName:String = DressPart.getDressNameByBonesName(boneName);
			var pack:DressPack = (_dressData[packName] as DressPack);
			if(pack == null || pack.state!=1) return null;
			var bone:BitmapData = pack.getResource(boneName);
			var boneOffset:Point = pack.getOffset(boneName);
			if(bone!=null)
			{
				var localX:int = data.x;//+90;
				var localY:int = data.y;//+135;
				var tp:Point;
				if(data.alternateRes!="")
				{
					//更换骨骼
					bone = pack.getResource(data.alternateRes);
				}
				_t.identity();
				var rad:Number = data.rotation*Math.PI/180;
				var isSmooth:Boolean = data.rotation==0?false:true;
				if(_flip)
				{												
					_t.rotate(rad);
					_t.scale(-data.scaleX,data.scaleY);
					tp= getTransformedOffset(boneOffset,-data.scaleX,data.scaleY,-rad,bmd.width-localX,localY);
					_t.translate(tp.x,tp.y);
					
					bmd.draw(bone,_t,null,null,null,isSmooth);
				}
				else
				{
					if(data.rotation!=0 || data.scaleX!=1 || data.scaleY!=1)
					{
						tp = getTransformedOffset(boneOffset,data.scaleX,data.scaleY,rad,localX,localY);
						_t.createBox(data.scaleX,data.scaleY,rad,tp.x,tp.y);
						bmd.draw(bone,_t,null,null,null,isSmooth);
					}
					else
					{
						tp = getTransformedOffset(boneOffset,data.scaleX,data.scaleY,rad,localX,localY);
						bmd.copyPixels(bone,bone.rect,tp,bone,new Point(0,0),true);
					}
				}
			}
			return bmd;
		}
		
		private function getLayerByName(name:String):Bitmap
		{
			for(var i:int = 0;i<_layers.length;i++ )
			{
				if(_layers[i].name == name)
					return _layers[i];
			}
			return null;
		}
			
		
		private function reset():void
		{
			
		}
		
		private var _t:Matrix = new Matrix();
		//先不缓存画两遍，第一遍用大矩形，第二遍用切过的矩形
		private function updateBonesAction():void
		{
			//var _t:Matrix=new Matrix();
			//if(_initDraw)
			
			//TODO:设置骨骼属性
			if(_aniData == null) return;
			var frameData:Array = _aniData[_curFrame-1] as Array;
			if(frameData == null)
			{
				
				//throw new Error("Bones:excced aniData boundaries");
				return;
			}
			
			var frameBmd:BitmapData;

			var needDrawLayer:Array = [];
			var needDraw:Boolean = false;
			//var fd:Vector.<uint>;
			var bmdCache:Array;
			
			
			for(var i:int = 0;i<_layers.length;i++)
			{
				var name:String = _chrType+_layers[i].name+"_"+_flip;
				bmdCache = ActorCacheManager.instance.getActionBMDCache(name,_actionName,_curFrame-1);
				if(bmdCache!=null)
				{
					_layers[i].bitmapData = bmdCache[0];
					var cacheRect:Rectangle = bmdCache[1];
					_layers[i].x = cacheRect.x;
					_layers[i].y = cacheRect.y;
				}
				else
				{
					needDrawLayer[_layers[i].name] = _layers[i];
					needDraw = true;
				}
			}
			
			
			if(!needDraw) return;
			
			for each(var bitmap:Bitmap in needDrawLayer)
			{
				bitmap.bitmapData.lock();
				//if(_layersRect[bitmap.name] == null)
				if(_currentPhase == 1)
				{
					var rect:Rectangle = _layersRect[bitmap.name];
					if(rect!=null)
					{
						bitmap.bitmapData = new BitmapData(rect.width,rect.height,true,0x00000000);
						bitmap.x = rect.x;
						bitmap.y = rect.y;
						//(_template[bitmap.name] as BitmapData).dispose();
						_template[bitmap.name] = bitmap.bitmapData.clone();
					}
					else
					{
						bitmap.bitmapData = _template[bitmap.name].clone();
					}
				}
				else
				{
					bitmap.bitmapData = _template[bitmap.name].clone();
				}
				if(_currentPhase == 0)
				{
					bitmap.x = 0;
					bitmap.y = 0;
				}
			} 
			
			//处理无翅膀角色问题，不传翅膀层，不传翅膀资源即可
			//TODO:优化无翅膀层的逻辑，没有翅膀层依然会遍历翅膀
			for(var i:int = 0;i<frameData.length;i++)
			{
				var data:BoneData = frameData[i] as BoneData;
				var name:String = data.name;
				var spliteName:String = name.split("_")[1];
				var drawLayerName:String;
				
				if(needDrawLayer["bone"]==null)
				{
					if(needDrawLayer[spliteName] == null)
						continue;
				}
				if(needDrawLayer[spliteName] != null)
				{
					frameBmd = needDrawLayer[spliteName].bitmapData;
					drawLayerName = spliteName;
					//data.x -= _layersOffset[spliteName].x;
					//data.y -= _layersOffset[spliteName].y;
				}
				else
				{
					frameBmd = needDrawLayer["bone"].bitmapData;
					drawLayerName = "bone";
					//data.x -= _layersOffset["bone"].x;
					///data.y -= _layersOffset["bone"].y;
				}
				
				if(_currentPhase >= 1)
				{
					if(_flip)
					{
						data.x += _layersRect[drawLayerName].x+frameBmd.width-_oriTemplate[drawLayerName].rect.width;	
					}
					else
					{
						data.x -= _layersRect[drawLayerName].x;
					}
					data.y -= _layersRect[drawLayerName].y;
				}
			

				drawByData(name,data,frameBmd);
				
				
				

				var otherParts:Array = DressPart.getExtraResByBoneName(name);
				if(otherParts!=null)
				{
					//添加被截掉的前缀
					var prefix:String = name.split("_")[0];
					if(prefix != "S" && prefix != "F")
						prefix = "";
					for(var m:int = 0;m<otherParts.length;m++)
					{
						drawByData(prefix+otherParts[m],data,frameBmd);
					}
					
				}
				//绘制完再加回来，防止元数据变化,优化？
				if(_currentPhase >= 1)
				{
					if(_flip)
					{
						data.x -= _layersRect[drawLayerName].x+frameBmd.width-_oriTemplate[drawLayerName].rect.width;
					}
					else
					{
						data.x += _layersRect[drawLayerName].x;
					}
					data.y += _layersRect[drawLayerName].y;
				}
				if(_currentPhase == 0)
				{
					var colordRect:Rectangle = frameBmd.getColorBoundsRect(0xffffff,0x00000000,false);
					if(colordRect.height!=0 && colordRect.width!=0)
					{
						if(_layersRect[drawLayerName] == null) 
							_layersRect[drawLayerName] = colordRect;
						else
						{
							var rect2:Rectangle = _layersRect[drawLayerName];  
							if(colordRect.top<rect2.top)
								rect2.top = colordRect.top;
							if(colordRect.left<rect2.left)
								rect2.left = colordRect.left;
							if(colordRect.bottom>rect2.bottom)
								rect2.bottom = colordRect.bottom;
							if(colordRect.right>rect2.right)
								rect2.right = colordRect.right;
							
						}
					}
					
				}
			}
			
			
			for each(var unlockBitmap:Bitmap in needDrawLayer)
			{
				unlockBitmap.bitmapData.unlock();
				
				if((_alternateFrame == 0 || _curFrame%_alternateFrame!=0) && _currentPhase==1){
					ActorCacheManager.instance.setActionBMDCache(unlockBitmap.bitmapData,_layersRect[unlockBitmap.name],_chrType+unlockBitmap.name+"_"+_flip,_actionName,_curFrame-1);
					
				}
			}
			
			
		
		}
	}
}